﻿namespace caedisi
{
    using System.Windows.Controls;
    using System.Windows.Navigation;
    using caedisi.Views;
    using caedisi.Models;
    using caedisi.Views.Controls;
    using caedisi.Helpers;
    using caedisi.Web.DataModel;
    using System.ComponentModel;
    using caedisi.Controller;
    using System;
    using caedisi.Common;
    using System.Windows.Data;
    using System.Windows;
    using System.Threading;
    using System.Windows.Threading;
    using System.Linq;
    using System.Collections.ObjectModel;
    using System.Text;

    /// <summary>
    /// Home page for the application.
    /// </summary>
    public partial class Inverter : Page, INotifyPropertyChanged
    {
        private object locker = new object(); 

        private CellularAutomata _CurrentCellularAutomata;
        /// <summary>
        /// Gets or sets the current cellular automata.
        /// </summary>
        /// <value>
        /// The current cellular automata.
        /// </value>
        public CellularAutomata CurrentCellularAutomata
        {
            get
            {
                return _CurrentCellularAutomata;
            }
            set
            {
                if (_CurrentCellularAutomata != value)
                {
                    _CurrentCellularAutomata = value;
                    this.RaisePropertyChanged("CurrentCellularAutomata");

                    OnCurrentCellularAutomataChanged(value);
                }
            }
        }

        private void OnCurrentCellularAutomataChanged(CellularAutomata value)
        {
            //directly create a simulation
            this.CurrentInverterExecution = new InverterExecution(this.CurrentCellularAutomata);
        }


        private InverterExecution _CurrentInverterExecution;
        /// <summary>
        /// Gets or sets the current simulation.
        /// </summary>
        /// <value>
        /// The current simulation.
        /// </value>
        public InverterExecution CurrentInverterExecution
        {
            get
            {
                return _CurrentInverterExecution;
            }
            set
            {
                if (_CurrentInverterExecution != value)
                {
                    _CurrentInverterExecution = value;
                    this.RaisePropertyChanged("CurrentInverterExecution");

                }
            }
        }

        /// <summary>
        /// Creates a new <see cref="Home"/> instance.
        /// </summary>
        public Inverter()
        {
            InitializeComponent();

            this.Title = ApplicationStrings.InverterTitle;
        }


        /// <summary>
        /// Executes when the user navigates to this page.
        /// </summary>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }


        /// <summary>
        /// Handles the Click event of the ButtonNewCellularAutomata control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonNewInverter_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            this.CurrentCellularAutomata = new CellularAutomata()
            {
                Width = Globals.Instance.DefaultNewCellularAutomataWidth,
                Height = Globals.Instance.DefaultNewCellularAutomataHeight,
                ImmunityTime = Globals.Instance.DefaultImmunityTime,
                RadiusContamination = Globals.Instance.DefaultRadiusContamination,
                RadiusVisibility = Globals.Instance.DefaultRadiusVisibility

            };

            InverterController.Instance.CurrentEntity = this.CurrentCellularAutomata;

            
            //show the New Cellular Parameters Window
            InverterParameters newInverterParameters = new InverterParameters(this.CurrentInverterExecution, this.CurrentCellularAutomata, Common.EnumInverterParametersEditMode.New);
            newInverterParameters.Show();
            newInverterParameters.Closed += new System.EventHandler(
                (s, ev) =>
                {                    
                    this.CurrentCellularAutomata = newInverterParameters.CurrentCellularAutomata;
                    if (newInverterParameters.DialogResult.Value == true)
                    {
                        this.CurrentCellularAutomata.CellularAutomataAsArray = new Cell[this.CurrentCellularAutomata.Height, this.CurrentCellularAutomata.Width, 1];
                         EntityHelper.SetCellularAutomataHierarchy(this.CurrentCellularAutomata, EnumCellStateType.Contaminated);
                         UIHelper.ConstructGridCellularAutomataUI(this.GridCellularAutomata, this.CurrentCellularAutomata.CellularAutomataAsArray, Globals.cellularAutomataGridMode_ColumnWidth, Globals.cellularAutomataGridMode_RowHeight);                           
                    }                
                }
                );
        }


        /// <summary>
        /// Handles the Click event of the ButtonStoreStates control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonStoreStates_Click(object sender, RoutedEventArgs e)
        {
            Collection<RuleValidationError> validationResultsCollisionRules = new Collection<RuleValidationError>();

            if (this.CurrentInverterExecution.CurrentStep > 0)
            {
                InverterController.Instance.ValidateAndStoreStates(this.CurrentInverterExecution, validationResultsCollisionRules);
            }

            if (validationResultsCollisionRules.Count > 0)
            {
                TransitionRulesValidationReport validationReportWindow = new TransitionRulesValidationReport(validationResultsCollisionRules, null);
                validationReportWindow.Show();
                validationReportWindow.Closed += new EventHandler((se, ev) =>
                {
                    ;
                });
            }
            else
            {
                this.CurrentInverterExecution.StoreStates();
                this.CurrentInverterExecution.CurrentStep += 1;

                //if the user automatically set the decontaminating state to be decontaminated 
                if (this.CurrentInverterExecution.IsDecontaminatingCleanInNextStep)
                {
                    foreach (Cell cell in this.CurrentCellularAutomata.Cells)
                    {
                        if (cell.CellStateTypeId == ((int)EnumCellStateType.Decontaminating))
                            cell.CellStateTypeId = (int)EnumCellStateType.Decontaminated;
                    }
                }
            }
        }

       

        /// <summary>
        /// Handles the Click event of the ButtonOpen control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonInputCompleted_Click(object sender, RoutedEventArgs e)
        {
            Collection<RuleValidationError> validationResultsCollisionRules = new Collection<RuleValidationError>();
 
            if (this.CurrentInverterExecution.CurrentStep > 0)
            {
                InverterController.Instance.ValidateAndStoreStates(this.CurrentInverterExecution, validationResultsCollisionRules);
            }

            if (validationResultsCollisionRules.Count>0)
            {
                TransitionRulesValidationReport validationReportWindow = new TransitionRulesValidationReport(validationResultsCollisionRules, null);
                validationReportWindow.Show();
                validationReportWindow.Closed += new EventHandler((se, ev) =>
                {
                    ;
                });
            }
            else
            {
                this.CurrentInverterExecution.StoreStates();

                this.CurrentInverterExecution.IsLastStepSet = true;
                this.CurrentInverterExecution.LastStep = this.CurrentInverterExecution.CurrentStep;
                MessageBox.Show("FirstStep=0 and " + "Last Step=" + this.CurrentInverterExecution.LastStep + Environment.NewLine + "Please use button below to navigate forward/backward");

            }
        }

        

        /// <summary>
        /// Handles the Click event of the ButtonTransferForSimulation control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonTransferForSimulation_Click(object sender, RoutedEventArgs e)
        {
            CellularAutomataController.Instance.CurrentEntity = ObjectCopier.Clone<CellularAutomata>(this.CurrentCellularAutomata);
            this.NavigationService.Navigate(new Uri("/Home", UriKind.Relative));
        }

       

        /// <summary>
        /// Handles the Click event of the ButtonVEditCAParameters control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonEditInverterParameters_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            //show the New Cellular Parameters Window
            InverterParameters editExistingInverterParametersWindow = new InverterParameters(this.CurrentInverterExecution, this.CurrentCellularAutomata, Common.EnumInverterParametersEditMode.Edit);
            editExistingInverterParametersWindow.Show();
            editExistingInverterParametersWindow.Closed += new System.EventHandler(EditExistingInverterParametersWindow_Closed);

        }

        /// <summary>
        /// Handles the Closed event of the EditExistingInverterParametersWindow control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void EditExistingInverterParametersWindow_Closed(object sender, System.EventArgs e)
        {
            ;
        }
       

        /// <summary>
        /// Handles the Click event of the ButtonFirstStep control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonFirstStep_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            this.CurrentInverterExecution.CurrentStep = 0;
        }

        /// <summary>
        /// Handles the Click event of the ButtonPreviousStep control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonPreviousStep_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (this.CurrentInverterExecution.CurrentStep == 0)
                return;

            this.CurrentInverterExecution.CurrentStep -=1;
            
        }

        /// <summary>
        /// Handles the Click event of the ButtonNextStep control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonNextStep_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            //this.TabControlCellularAutomataAndInverterExecutionInfo.SelectedIndex = 1;
            this.CurrentInverterExecution.CurrentStep += 1;
        }

        /// <summary>
        /// Handles the Click event of the ButtonLastStep control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonLastStep_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            this.CurrentInverterExecution.CurrentStep = this.CurrentInverterExecution.LastStep;
        }

 
        /// <summary>
        /// Handles the Click event of the ButtonResetAllCellState control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonResetAllCellState_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (this.CurrentCellularAutomata == null)
            {
                MessageBox.Show("Please create or open an existing Cellular Automata first.");
            }
            else if (this.BasicCellControlResetState.SelectedCellStateTypeId==null || this.BasicCellControlResetState.SelectedCellStateTypeId == 0)
            {
                MessageBox.Show("Please select a state first.");
            }
            else
            {
                foreach (Cell cell in this.CurrentCellularAutomata.Cells)
                    cell.CellStateTypeId = this.BasicCellControlResetState.SelectedCellStateTypeId.Value;
            }
       }
       

        /// <summary>
        /// Handles the Click event of the ButtonSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonSave_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (InverterController.Instance.HasChanges)
            {
                MessageBoxResult result = MessageBox.Show("Do you really wanna perform the save?", "Confirm Saving Cellular Automata", MessageBoxButton.OKCancel);
                if (result == MessageBoxResult.OK)
                {

                    if (this.CurrentCellularAutomata.ImmunityTime > 0)
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.Append("Contamination Rules will be created by default. ");
                        NeighbourhoodType neighbourhoodType = EntityHelper.GetNeighbourhoodType(CurrentCellularAutomata.NeighbourhoodTypeId);
                        int numberOfRulesCreated = CurrentCellularAutomata.TransitionRules.Count;
                        EntityHelper.GenerateContaminationRule(this.CurrentCellularAutomata, neighbourhoodType, ref numberOfRulesCreated);
                        MessageBox.Show(sb.ToString(), "Information", MessageBoxButton.OK);
                    }


                    InverterController.Instance.Save(
                        (sucess, exception) =>
                        {
                            if (sucess)
                                MessageBox.Show("Your change has been saved.");
                            else
                            {
                                MessageBox.Show("Error happened when saving the data. Exception is below" + Environment.NewLine + exception.ToString());
                            }
                        }
                    );
                }
            }
            else
            {
                MessageBox.Show("There is nothing save");
            }                                  
        }



        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// Raises the property changed.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        protected virtual void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        
                          
    }
}